上一篇利用路由機制傳遞參數來實作待辦事項的編輯功能,除了透過網址路徑來傳遞所需要的參數,還可以在路由定義中透過 resolve
屬性物件來指定 Resolve 服務,Angular 會先利用此服務取得資料後,才進行頁面元件的載入。
首先,在終端機執行 ng g s task/resolve/task-resolve
來建立 TaskResolveService,並在服務實作 Resolve<Task>
介面。
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class TaskResolveService implements Resolve<Task> {
constructor() {}
resolve(route: ActivatedRouteSnapshot): Observable<Task> | Promise<Task> | Task {}
}
接下來,會在 router()
方法實作待辦事項資料取得,可以利用傳入的 ActivatedRouteSnapshot 物件來取得待辦事項編號。
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class TaskResolveService implements Resolve<Task> {
constructor(private taskService: TaskRemoteService) {}
resolve(route: ActivatedRouteSnapshot): Observable<Task> {
const id = +route.paramMap.get('id');
return this.taskService.get(id);
}
}
然後在 app-routing.module.ts 中的待辦事項編輯路由中,加入 resolve
物件屬性,就可以讓 Angular 在載入表單頁面前取得待辦事項資料。
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'main' },
{ path: 'main', component: MainPageComponent },
{ path: 'task-list', component: TaskPageComponent },
{ path: 'task-form', component: TaskFormComponent },
{
path: 'task-form/:id',
component: TaskFormComponent,
resolve: {
task: TaskResolveService,
},
},
];
最後,在 task-form.component.ts 中,利用 ActivatedRoute 服務元件內的 data
屬性來取得所傳入的待辦事項資料。
export class TaskFormComponent implements OnInit, OnDestroy {
constructor(private fb: FormBuilder, private router: Router, private route: ActivatedRoute, private taskService: TaskRemoteService) {}
ngOnInit(): void {
this.route.data
.pipe(
map(({ task }: { task: Task }) => task),
filter((task) => !!task),
tap(() => this.tags.clear()),
tap((task) => this.onAddTag(task.tags.length)),
takeUntil(this.stop$)
)
.subscribe((task) => this.form.patchValue(task));
}
}
利用 Chrome DevTool 可以看到目前所開發的程式,會封裝成 main.js 載入至用戶端。在開發較複雜的 Angular 應用程式時,有時會需要減少運行時所載入的 js 檔案大小,以讓使用者能更快速的看到頁面內容。此時,就可以利用延遲載入 (Lazy Loading) 機制,在使用者選點頁面時,才依模組為單位載入對應的 js 檔案。
首先,在 Task 模組中加入 task-routing.module.ts 檔案,且將與待辦事項相關的路由移至此,並在 Task 模組匯入。
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TaskResolveService } from './resolve/task-resolve.service';
import { TaskFormComponent } from './task-form/task-form.component';
import { TaskPageComponent } from './task-page/task-page.component';
const routes: Routes = [
{ path: 'list', component: TaskPageComponent },
{ path: 'form', component: TaskFormComponent },
{
path: 'form/:id',
component: TaskFormComponent,
resolve: {
task: TaskResolveService,
},
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class TaskRoutingModule {}
接著在 app-routing.module.ts 中利用 loadChildren
設定載入待辦事項模組,當路由器導覽到 task 路由時,會動態載入 Task 模組,並將 Task 模組內的路由加入配置中。另外,由於路由路徑已調整,因此需要變更 app.component.html 中的導覽列設定。
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'main' },
{ path: 'main', component: MainPageComponent },
{
path: 'task',
loadChildren: () => import('./task/task.module').then((m) => m.TaskModule),
},
];
<nav>
<a [routerLink]="['main']" routerLinkActive="active">首頁</a>
<a [routerLink]="['task', 'list']" routerLinkActive="active">待辦事項</a>
</nav>
<router-outlet></router-outlet>
需注意一點,由於 Task 模組將會被動態載入,所以在 app.module.ts 中需要移除本來匯入的 Task 模組。利用 Chrome DevTool 可以看到,原來的 main.js 檔案大小減少,且在點選待辦事項功能時會載入 task-task.module.js。
這一篇利用 resolve 來預先取得頁面所需要資料才載入頁面元件;並利用延遲載入 (Lazy Loading) 來依模組為單位載入所需要的檔案。